package game.leon.engine.net.codec;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

/**
 * User: bianpeng
 * Date: 11-12-27
 *
 * 设计注意点
 * 1. 这里的prefix中, 长度2字节, 没有问题
 * 2. userId, 4字节, 客户端传上来的userId是不可信的, 需要服务端自行记录.
 * 跟逻辑服务器通信的时候, userId才会有效. 地位相当于session.
 * 可以考虑设置模式, 这样, 客户端就不必上传这个数据了
 * 3. message, 2字节, 用于不解析就能处理消息用的, 减少多余的序列化, 反序列化
 *
 */
class GateProtocolDecoder extends CumulativeProtocolDecoder {
    private static final String DECODE_STATE = "DECODE_STATE";
    public static final int BUFFER_PREFIX_LENGTH = 6; // 2 data length, 4 userId, 2 message

    @Override
    protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
        DecodeState state = (DecodeState) session.getAttribute(DECODE_STATE);
        if (state == null) {
            state = new DecodeState();
            session.setAttribute(DECODE_STATE, state);
        }

        if (state.step == 0) {
            if (in.remaining() > BUFFER_PREFIX_LENGTH) {
                // 这里是实际数据长度, 8字节的PREFIX长度, 不包含在内
                state.datasize = in.getUnsignedShort();
                state.userId = in.getUnsignedInt();

                state.step = 1;
            }
        }
        if (state.step == 1 && in.remaining() >= state.datasize) {
            int message = in.getUnsignedShort();
            byte[] data = new byte[state.datasize - 2];
            in.get(data);
            out.write(new GateRawMessage(state.userId, message, data));
            state.step = 0;
            return true;
        }
        return false;
    }
    private static class DecodeState {
        int step;
        // 2 bytes datasize
        // 4 bytes userId
        // 2 bytes message
        int datasize;
        long userId;
    }
}
